package com.jinunn.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jinunn.system.common.constant.SystemConstants;
import com.jinunn.system.converter.RoleConverter;
import com.jinunn.system.entity.Role;
import com.jinunn.system.entity.RoleMenu;
import com.jinunn.system.exception.BusinessException;
import com.jinunn.system.mapper.RoleMapper;
import com.jinunn.system.model.params.RoleMenusParam;
import com.jinunn.system.model.params.RoleParam;
import com.jinunn.system.model.query.RolePageQuery;
import com.jinunn.system.model.vo.role.RolePageVO;
import com.jinunn.system.secutity.utils.SecurityUtils;
import com.jinunn.system.service.RoleMenuService;
import com.jinunn.system.service.RoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinunn.system.service.UserRoleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author JIN
 * @since 2024-07-11
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    private final RoleMenuService roleMenuService;
    private final RoleConverter roleConverter;
    private final UserRoleService userRoleService;

    @Override
    public Integer getMaximumDataScope(Set<String> roles) {
        return this.baseMapper.getMaximumDataScope(roles);
    }

    @Override
    public Page<RolePageVO> getPage(RolePageQuery queryParams) {
        // 非超级管理员不显示超级管理员角色
        return baseMapper.getPage(queryParams.toPage(), queryParams);
    }

    @Override
    public boolean saveRole(RoleParam roleForm) {
        String roleCode = roleForm.getCode();
        Long count = this.lambdaQuery().eq(Role::getCode, roleCode).count();
        Assert.isTrue(count == 0, () -> new BusinessException("角色名称或角色编码已存在"));
        Role role = roleConverter.convertToEntity(roleForm);
        return this.save(role);
    }

    @Override
    public boolean editRole(RoleParam roleForm) {
        Role oldRole = this.getById(roleForm.getId());
        Assert.notNull(oldRole, () -> new BusinessException("角色不存在"));

        Long count = this.lambdaQuery()
                .eq(Role::getCode, roleForm.getCode()).count();
        Assert.isTrue(count == 0, () -> new BusinessException("角色名称或角色编码已存在"));

        // 实体转换
        Role newRole = roleConverter.convertToEntity(roleForm);
        boolean result = this.updateById(newRole);
        if (result) {
            if (Objects.nonNull(oldRole)
                    && !StringUtils.equals(oldRole.getCode(), newRole.getCode())
                    && !ObjectUtil.equals(oldRole.getStatus(), newRole.getStatus())) {
                roleMenuService.refreshRolePermsCache(oldRole.getCode(), newRole.getCode());
            }
        }
        return result;
    }

    @Override
    public boolean deleteRole(Long id) {
        Role role = this.getById(id);
        Assert.notNull(role, () -> new BusinessException("角色不存在"));

        boolean isRoleAssigned = userRoleService.hasAssignedUsers(id);
        Assert.isTrue(!isRoleAssigned, () -> new BusinessException("角色【{}】已分配用户，请先解除关联后删除", role.getName()));

        boolean result = this.removeById(id);
        if (result) {
            // 删除成功，刷新权限缓存
            roleMenuService.refreshRolePermsCache(role.getCode());
        }
        return true;
    }

    @Override
    public boolean assignMenusToRole(RoleMenusParam param) {
        Role role = this.getById(param.getRoleId());
        Assert.notNull(role, () -> new BusinessException("角色不存在"));

        // 删除角色菜单
        roleMenuService.remove(new LambdaQueryWrapper<RoleMenu>()
                .eq(RoleMenu::getRoleId, param.getRoleId()));

        // 新增角色菜单
        if (CollectionUtil.isNotEmpty(param.getMenuIds())) {
            List<RoleMenu> roleMenus = param.getMenuIds()
                    .stream()
                    .map(menuId -> new RoleMenu(param.getRoleId(), menuId))
                    .toList();
            roleMenuService.saveBatch(roleMenus);
        }
        // 刷新角色的权限缓存
        roleMenuService.refreshRolePermsCache(role.getCode());
        return Boolean.TRUE;
    }
}
